﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace UtilZ.Dotnet.Ex.Log
{
    /// <summary>
    /// 日志记录器基类
    /// </summary>
    public abstract class LogerCoreAbs : ILogerCore
    {
        /// <summary>
        /// 日志追加器集合
        /// </summary>
        protected readonly List<IAppender> _appenders = new List<IAppender>();

        /// <summary>
        /// 日志追加器集合线程锁
        /// </summary>
        protected readonly object _appendersLock = new object();

        /// <summary>
        /// 构造函数
        /// </summary>
        public LogerCoreAbs()
        {

        }



        #region ILoger接口
        /// <summary>
        /// 日志记录器名称
        /// </summary>
        protected string _name = null;
        /// <summary>
        /// 获取日志记录器名称
        /// </summary>
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        /// <summary>
        /// 获取获取日志级别
        /// </summary>
        public LogLevel Level { get; set; } = LogLevel.Trace;

        /// <summary>
        /// 是否启用日志追加器
        /// </summary>
        public bool Enable { get; set; } = true;

        private LogLevel[] _outputStackLevels = null;
        /// <summary>
        /// 需要输出堆栈信息的日志级别
        /// </summary>
        public LogLevel[] OutputStackLevels
        {
            get { return this._outputStackLevels; }
            set { this._outputStackLevels = value; }
        }

        /// <summary>
        /// 添加日志追加器
        /// </summary>
        /// <param name="appender">日志追加器</param>
        public void AddAppender(IAppender appender)
        {
            if (appender == null)
            {
                return;
            }

            lock (this._appendersLock)
            {
                this._appenders.Add(appender);
            }
        }

        /// <summary>
        /// 移除日志追加器
        /// </summary>
        /// <param name="appender">日志追加器</param>
        public void RemoveAppender(IAppender appender)
        {
            if (appender == null)
            {
                return;
            }

            lock (this._appendersLock)
            {
                this._appenders.Remove(appender);
            }
        }

        /// <summary>
        /// 清空日志追加器
        /// </summary>
        public void ClearAppender()
        {
            lock (this._appendersLock)
            {
                this._appenders.Clear();
            }
        }

        /// <summary>
        /// 根据日志追加器名称获取日志追加器
        /// </summary>
        /// <param name="appenderName">日志追加器名称</param>
        /// <returns>日志追加器</returns>
        public IAppender GetAppenderByName(string appenderName)
        {
            lock (this._appendersLock)
            {
                return this._appenders.Where(t =>
                {
                    return appenderName == null && string.IsNullOrEmpty(t.Name) ||
                    t.Name == null && string.IsNullOrEmpty(appenderName) ||
                    string.Equals(t.Name, appenderName);
                }).FirstOrDefault();
            }
        }

        /// <summary>
        /// 获取日志追加器
        /// </summary>
        /// <returns>日志追加器数组</returns>
        public IAppender[] GetAppenders()
        {
            lock (this._appendersLock)
            {
                return this._appenders.ToArray();
            }
        }








        #region 记录日志方法
        /// <summary>
        /// Loger添加日志的方法
        /// </summary>
        /// <param name="logItem">日志对象</param>
        public void Log(LogItem logItem)
        {
            this.PrimitiveLog(logItem);
        }

        /// <summary>
        /// 实例添加日志
        /// </summary>
        /// <param name="logItem">日志项</param>
        protected abstract void PrimitiveLog(LogItem logItem);

        #endregion
        #endregion


        #region IDisposable接口

        private bool _disposed = false;
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (this._disposed)
            {
                return;
            }
            this._disposed = true;

            this.Dispose(true);
        }

        /// <summary>
        /// 释放资源方法
        /// </summary>
        /// <param name="isDisposing">是否释放标识</param>
        protected virtual void Dispose(bool isDisposing)
        {

        }

        #endregion
    }
}
